package com.huantai.common.util.image;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import com.huantai.common.enums.PictureFormatEnum;
import com.huantai.common.enums.WaterMarkPositionEnum;

/**
 * 水印工具类
 * 
 * @author Ma Chao
 * @version 2017年12月26日 上午10:40:03
 */
public final class WaterMarkUtil {
    private WaterMarkUtil() {}

    /** 默认水印距离图片边缘的间距 */
    private static final int DEFAULT_MARGIN = 20;

    /**
     * 添加图片水印
     *
     * @param targetImgFilePath 要添加水印的JPG文件全路径，例如：D:\\pictures\\test.jpg
     * @param waterImgFilePath 水印图片文件全路径，例如：D:\\pictures\\mark.png
     * @param position 水印相对于图片的位置枚举
     * @param alpha 透明度(0.0-1.0, 0.0为完全透明，1.0为完全不透明)
     * @param margin 水印距离图片边缘的间距
     * @throws IOException
     */
    public static void waterMarkWithImg(String targetImgFilePath, String waterImgFilePath,
                                        WaterMarkPositionEnum position, float alpha, int margin) throws IOException {
        // 0、读取图片获得图片数据、图片宽度、高度
        File file = new File(targetImgFilePath);
        Image image = ImageIO.read(file);
        int width = image.getWidth(null);
        int height = image.getHeight(null);
        // 1、得到画笔对象，并重新绘制目标图片
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bufferedImage.createGraphics();
        g.drawImage(image, 0, 0, width, height, null);
        // 2、水印信息
        Image waterImage = ImageIO.read(new File(waterImgFilePath));
        int waterImgWidth = waterImage.getWidth(null);
        int waterImgHeight = waterImage.getHeight(null);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

        // 4、根据位置计算文本所处的位置
        int x = getPositionX(width, waterImgWidth, position, margin);
        int y = getPositionY(height, waterImgHeight, position, margin);
        // 5、绘制水印图片
        g.drawImage(waterImage, x, y, waterImgWidth, waterImgHeight, null);
        // 6、释放资源
        g.dispose();
        ImageIO.write(bufferedImage, PictureFormatEnum.PNG.getValue(), file);
    }

    /**
     * 添加文字水印并铺满目标图片， 建议根据图片大小来确定水印字体大小和间距，根据图片中颜色来确定水印颜色和透明度
     * 
     * @param targetImgFilePath 要添加水印的JPG文件全路径，例如：D:\\pictures\\test.jpg
     * @param waterImgFilePath 水印图片文件全路径，例如：D:\\pictures\\mark.png
     * @param alpha 透明度(0.0-1.0, 0.0为完全透明，1.0为完全不透明)
     * @param degree 旋转角度(正数顺时针旋转，负数逆时针旋转)，例如：-8
     * @param interval 间距，正整数，例如：150
     * @throws IOException
     */
    public static void waterMarkWithImgRepeat(String targetImgFilePath, String waterImgFilePath,
            float alpha, double degree, int interval) throws IOException {
        // 0、读取图片获得图片数据、图片宽度、高度
        File file = new File(targetImgFilePath);
        Image image = ImageIO.read(file);
        int width = image.getWidth(null);
        int height = image.getHeight(null);
        // 1、得到画笔对象
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bufferedImage.createGraphics();
        // 2、设置对线段的锯齿状边缘处理
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
        // 3、设置水印旋转角度
        if (0 != degree) {
            g.rotate(Math.toRadians(degree), (double) bufferedImage.getWidth() / 2,
                    (double) bufferedImage.getHeight() / 2);
        }

        // 4、水印图片的宽度和高度
        Image waterImage = ImageIO.read(new File(waterImgFilePath));
        int waterImgWidth = waterImage.getWidth(null);
        int waterImgHeight = waterImage.getHeight(null);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

        // 5、绘制水印图片
        for (int waterMarkHeight = 0; waterMarkHeight <= height + interval
                + waterImgHeight; waterMarkHeight = waterMarkHeight + interval + waterImgHeight) {
            for (int waterMarkWidth = 0; waterMarkWidth <= width + interval
                    + waterImgWidth; waterMarkWidth = waterMarkWidth + interval + waterImgWidth) {
                g.drawImage(waterImage, waterMarkWidth - waterImgWidth,
                        waterMarkHeight - waterImgHeight, waterImgWidth, waterImgHeight, null);
            }
        }
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        // 6、释放资源
        g.dispose();
        ImageIO.write(bufferedImage, PictureFormatEnum.PNG.getValue(), file);
    }

    /**
     * 添加文字水印
     * 
     * @param targetImgFilePath 要添加水印的JPG文件全路径，例如：D:\\pictures\\test.jpg
     * @param waterMarkText 水印字符串，例如：张三2017 紫金普惠
     * @param font 水印文字字体
     * @param color 字体颜色
     * @param position 水印相对于图片的位置枚举
     * @param alpha 透明度(0.0-1.0, 0.0为完全透明，1.0为完全不透明)
     * @param margin 水印距离图片边缘的间距
     * @throws IOException
     */
    public static void waterMarkWithText(String targetImgFilePath, String waterMarkText, Font font,
            Color color, WaterMarkPositionEnum position, float alpha, int margin)
            throws IOException {
        // 0、读取图片获得图片数据、图片宽度、高度
        File file = new File(targetImgFilePath);
        Image image = ImageIO.read(file);
        int width = image.getWidth(null);
        int height = image.getHeight(null);
        // 1、得到画笔对象，并重新绘制目标图片
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bufferedImage.createGraphics();
        g.drawImage(image, 0, 0, width, height, null);
        // 2、字体、颜色、透明度
        g.setFont(font);
        g.setColor(color);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

        // 3、文本的宽度和高度
        int textWidth = font.getSize() * getTextLength(waterMarkText);
        int textHeight = font.getSize();

        // 4、根据位置计算文本所处的位置
        int x = getPositionX(width, textWidth, position, margin);
        int y = getPositionY(height, textHeight, position, margin);
        // 5、绘制水印图片
        g.drawString(waterMarkText, x, y);
        // 6、释放资源
        g.dispose();
        ImageIO.write(bufferedImage, PictureFormatEnum.PNG.getValue(), file);
    }

    /**
     * 添加文字水印并铺满目标图片， 建议根据图片大小来确定水印字体大小和间距，根据图片中颜色来确定水印颜色和透明度
     * 
     * @param targetImgFilePath 要添加水印的JPG文件全路径，例如：D:\\pictures\\test.jpg
     * @param waterMarkText 水印字符串，例如：张三2017 紫金普惠
     * @param font 水印字体
     * @param color 水印颜色
     * @param alpha 透明度(0.0-1.0, 0.0为完全透明，1.0为完全不透明)
     * @param degree 旋转角度(正数顺时针旋转，负数逆时针旋转)，例如：-8
     * @param interval 间距，正整数，例如：150
     * @throws IOException
     */
    public static void waterMarkWithTextRepeat(String targetImgFilePath, String waterMarkText,
            Font font, Color color, float alpha, double degree, int interval) throws IOException {
        // 0、读取图片获得图片数据、图片宽度、高度
        File file = new File(targetImgFilePath);
        Image image = ImageIO.read(file);
        int width = image.getWidth(null);
        int height = image.getHeight(null);
        // 1、得到画笔对象
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bufferedImage.createGraphics();
        // 2、设置对线段的锯齿状边缘处理
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
        // 3、设置水印旋转角度
        if (0 != degree) {
            g.rotate(Math.toRadians(degree), (double) bufferedImage.getWidth() / 2,
                    (double) bufferedImage.getHeight() / 2);
        }
        // 4、字体、颜色、透明度
        g.setFont(font);
        g.setColor(color);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

        // 5、文本的宽度和高度
        int textWidth = font.getSize() * getTextLength(waterMarkText);
        int textHeight = font.getSize();

        // 6、绘制水印图片
        for (int waterMarkHeight = 0; waterMarkHeight <= height + interval
                + textHeight; waterMarkHeight = waterMarkHeight + interval + textHeight) {
            for (int waterMarkWidth = 0; waterMarkWidth <= width + interval
                    + textWidth; waterMarkWidth = waterMarkWidth + interval + textWidth) {
                g.drawString(waterMarkText, waterMarkWidth - textWidth,
                        waterMarkHeight - textHeight);
            }
        }
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        // 7、释放资源
        g.dispose();
        ImageIO.write(bufferedImage, PictureFormatEnum.PNG.getValue(), file);
    }

    /**
     * 获取字符长度， 一个汉字作为1个字符，一个英文字母或空格作为 0.5个字符。
     * 
     * @param text 字符串
     * @return 字符长度
     */
    private static int getTextLength(String text) {
        int textLength = text.length();
        int length = textLength;
        for (int i = 0; i < textLength; i++) {
            if (String.valueOf(text.charAt(i)).getBytes().length > 1) {
                length++;
            }
        }
        return (length % 2 == 0) ? length / 2 : length / 2 + 1;
    }

    /**
     * 根据水印定位信息计算水印水平位置
     * 
     * @param width 目标图片的宽度
     * @param waterMarkWidth 水印宽度
     * @param position 定位信息
     * @param margin 水印距离图片边缘的间距
     * @return 水印水平位置
     */
    private static int getPositionX(int width, int waterMarkWidth, WaterMarkPositionEnum position,
            int margin) {
        int x = 0;
        if (0 >= margin) {
            margin = DEFAULT_MARGIN;
        }
        // 水平居左
        if (WaterMarkPositionEnum.BOTTOM_LEFT == position
                || WaterMarkPositionEnum.MIDDLE_LEFT == position
                || WaterMarkPositionEnum.TOP_LEFT == position) {
            x = margin;
        }
        // 水平居右
        if (WaterMarkPositionEnum.BOTTOM_RIGHT == position
                || WaterMarkPositionEnum.MIDDLE_RIGHT == position
                || WaterMarkPositionEnum.TOP_RIGHT == position) {
            x = width - waterMarkWidth - margin;
        }
        // 水平居中
        if (WaterMarkPositionEnum.BOTTOM_CENTER == position
                || WaterMarkPositionEnum.MIDDLE_CENTER == position
                || WaterMarkPositionEnum.TOP_CENTER == position) {
            x = (width - waterMarkWidth - margin) / 2;
        }
        return x;
    }

    /**
     * 根据水印定位信息计算水印垂直位置
     * 
     * @param height 目标图片的高度
     * @param waterMarkWidth 水印高度
     * @param position 定位信息
     * @param margin 水印距离图片边缘的间距
     * @return 水印垂直位置
     */
    private static int getPositionY(int height, int waterMarkHeight, WaterMarkPositionEnum position,
            int margin) {
        int y = 0;
        if (0 >= margin) {
            margin = DEFAULT_MARGIN;
        }
        // 垂直居上
        if (WaterMarkPositionEnum.TOP_LEFT == position
                || WaterMarkPositionEnum.TOP_CENTER == position
                || WaterMarkPositionEnum.TOP_RIGHT == position) {
            y = waterMarkHeight + margin;
        }
        // 垂直居下
        if (WaterMarkPositionEnum.BOTTOM_LEFT == position
                || WaterMarkPositionEnum.BOTTOM_CENTER == position
                || WaterMarkPositionEnum.BOTTOM_RIGHT == position) {
            y = height - waterMarkHeight - margin;
        }
        // 垂直居中
        if (WaterMarkPositionEnum.MIDDLE_LEFT == position
                || WaterMarkPositionEnum.MIDDLE_CENTER == position
                || WaterMarkPositionEnum.MIDDLE_RIGHT == position) {
            y = (height - waterMarkHeight - margin) / 2;
        }
        return y;
    }

}
